package org.opencv.android;

import android.content.Context;
import android.hardware.Camera;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.Display;
import android.view.Surface;
import android.view.WindowManager;
import android.widget.ImageView;
import java.lang.reflect.Method;
import java.util.List;
import org.opencv.BuildConfig;
import org.opencv.core.Mat;
import org.opencv.core.Size;

public abstract class CsizgCameraBridgeViewBase extends CameraBridgeViewBase {

    protected ImageView mImageView;
    protected WindowManager mWindowManager;

    public CsizgCameraBridgeViewBase(Context context, int cameraId) {
        super(context, cameraId);
    }

    public CsizgCameraBridgeViewBase(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void bindImageView(ImageView imageView) {
        this.mImageView = imageView;
    }

    public int getCameraIndex() {
        return this.mCameraIndex;
    }

    public void setWindowManager(WindowManager windowManager) {
        this.mWindowManager = windowManager;
    }

    protected void deliverAndDrawFrame(CvCameraViewFrame frame) {
        Mat modified;

        if (mListener != null) {
            modified = mListener.onCameraFrame(frame);
        } else {
            modified = frame.rgba();
        }
    }

    /** 获取虚拟功能键高度 */
    public int getVirtualBarHeight(Context context) {
        int vh = 0;
        WindowManager windowManager =
                (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
        Display display = windowManager.getDefaultDisplay();
        DisplayMetrics dm = new DisplayMetrics();
        try {
            @SuppressWarnings("rawtypes") Class c = Class.forName("android.view.Display");
            @SuppressWarnings("unchecked") Method method =
                    c.getMethod("getRealMetrics", DisplayMetrics.class);
            method.invoke(display, dm);
            vh = dm.heightPixels - windowManager.getDefaultDisplay().getHeight();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return vh;
    }

    protected Size calculateCameraFrameSize(boolean portrait, List<?> supportedSizes,
            ListItemAccessor accessor, int surfaceWidth, int surfaceHeight) {
        int calcWidth = 0;
        int calcHeight = 0;

        int statusBarHeight = -1;
        //获取status_bar_height资源的ID
        int resourceId = getResources().getIdentifier("status_bar_height", "dimen", "android");
        if (resourceId > 0) {
            //根据资源ID获取响应的尺寸值
            statusBarHeight = getResources().getDimensionPixelSize(resourceId);
        }
        int virtualBarHeight = getVirtualBarHeight(this.getContext());
        surfaceHeight += statusBarHeight + virtualBarHeight;
        if (BuildConfig.DEBUG) {
            System.out.println(surfaceWidth + "<------3------>" + surfaceHeight);
        }

        int maxAllowedWidth = (mMaxWidth != MAX_UNSPECIFIED && mMaxWidth < surfaceWidth) ? mMaxWidth
                : surfaceWidth;
        int maxAllowedHeight =
                (mMaxHeight != MAX_UNSPECIFIED && mMaxHeight < surfaceHeight) ? mMaxHeight
                        : surfaceHeight;
        if (portrait) {
            maxAllowedWidth =
                    (mMaxHeight != MAX_UNSPECIFIED && mMaxHeight < surfaceHeight) ? mMaxHeight
                            : surfaceHeight;
            maxAllowedHeight =
                    (mMaxWidth != MAX_UNSPECIFIED && mMaxWidth < surfaceWidth) ? mMaxWidth
                            : surfaceWidth;
        }

        for (Object size : supportedSizes) {
            int width = accessor.getWidth(size);
            int height = accessor.getHeight(size);

            if (width <= maxAllowedWidth && height <= maxAllowedHeight) {
                if (width >= calcWidth && height >= calcHeight) {
                    calcWidth = (int) width;
                    calcHeight = (int) height;
                }
            }
        }

        return new Size(calcWidth, calcHeight);
    }

    private int mDisplayOrientation = 0;

    protected void setCameraDisplayOrientation(WindowManager windowManager, int cameraId,
            android.hardware.Camera camera) {
        int localCameraIndex = -1;
        Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
        for (int camIdx = 0; camIdx < Camera.getNumberOfCameras(); ++camIdx) {
            Camera.getCameraInfo(camIdx, cameraInfo);
            if (cameraId == CAMERA_ID_BACK) {
                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {
                    localCameraIndex = camIdx;
                    break;
                }
            } else if (cameraId == CAMERA_ID_FRONT) {
                if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
                    localCameraIndex = camIdx;
                    break;
                }
            } else if (cameraId == CAMERA_ID_ANY) {
                localCameraIndex = camIdx;
                break;
            }
        }

        android.hardware.Camera.CameraInfo info = new android.hardware.Camera.CameraInfo();
        android.hardware.Camera.getCameraInfo(localCameraIndex, info);
        int rotation = windowManager.getDefaultDisplay().getRotation();
        int degrees = 0;
        switch (rotation) {
            case Surface.ROTATION_0:
                degrees = 0;
                break;
            case Surface.ROTATION_90:
                degrees = 90;
                break;
            case Surface.ROTATION_180:
                degrees = 180;
                break;
            case Surface.ROTATION_270:
                degrees = 270;
                break;
        }

        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360;  // compensate the mirror
        } else {  // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        if (BuildConfig.DEBUG) {
            System.out.println("setCameraDisplayOrientation result = " + result);
        }
        camera.setDisplayOrientation(result);
        mDisplayOrientation = result;
    }

    public int getDisplayOrientation() {
        return mDisplayOrientation;
    }
}
